package com.qf.controller;

import com.event.util.EventUtil;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.qf.entity.Goods;
import com.qf.entity.R;
import com.qf.feign.GoodsFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.imageio.ImageIO;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/kill")
@CrossOrigin
public class KillController {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private DefaultKaptcha kaptcha;

    @Autowired
    private GoodsFeign goodsFeign;

    @Autowired
    private EventUtil eventUtil;

    private String lua = "--下单的商品id号\n" +
            "local gid = KEYS[1]\n" +
            "--获取库存\n" +
            "local save = tonumber(redis.call(\"get\", \"goods\"..gid))\n" +
            "--判断库存\n" +
            "if save >= 1 then \n" +
            "  -- 库存足够\n" +
            "  save = redis.call(\"decr\", \"goods\"..gid)\n" +
            "  --返回剩余库存\n" +
            "  return save\n" +
            "end\n" +
            "--库存不够\n" +
            "return -1";

    /**
     * 立即抢购的逻辑
     * @return
     */
    @RequestMapping("/seckill")
    public R secKill(Integer gid, Integer uid){
        Goods goods = (Goods) redisTemplate.opsForValue().get("goods_details_" + gid);
        if (goods == null || goods.getBeginTime().getTime() > new Date().getTime()) {
            //商品未开抢
            return new R().setCode(R.CODE.ERROR).setMsg("商品还未开抢！");
        }

        //该商品可以处理下单逻辑
        Long flag = stringRedisTemplate.execute(new DefaultRedisScript<Long>(lua, Long.class),
                Collections.singletonList(gid + ""));

        if (flag != -1) {
            //下单成功 - 将消息放入MQ中，通知商品服务和订单服务同步到数据库
            Map map = new HashMap();
            map.put("gid", gid);
            map.put("uid", uid);
            eventUtil.sendMsg("orders_msg", map, true);

            return new R().setData("success");
        }

        //抢购失败！
        return new R().setCode(R.CODE.ERROR).setMsg("下单失败，原因：库存不足!");
    }

    /**
     * 获取验证码
     */
    @RequestMapping("/code")
    public void getCode(String uuid, HttpServletResponse response){
        //生成验证码
        String code = kaptcha.createText();
        //根据验证码生成图片
        BufferedImage imageIO = kaptcha.createImage(code);

        //暂存验证码
        stringRedisTemplate.opsForValue().set("code_" + uuid, code, 5, TimeUnit.MINUTES);
        System.out.println(uuid + " 验证码为：" + code);

        //写入到前端
        try {
            ServletOutputStream out = response.getOutputStream();
            ImageIO.write(imageIO, "jpg", out);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置提醒
     */
    @RequestMapping("/tixing")
    public R tixing(Integer uid, Integer gid){

        //根据id查询商品信息
        Goods goods = goodsFeign.getGoodById(gid).getData();

        //解析商品开抢前5分钟的 - 年月日时分
        Date date = goods.getBeginTime();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, -5);
        Date tixingTime = calendar.getTime();
        //格式化时间
        String time = new SimpleDateFormat("yyMMddHHmm").format(tixingTime);

        //使用redis管理提醒消息
        String msg = uid + "_" + gid;
        boolean falg = stringRedisTemplate.opsForZSet().add("tixing_zset", msg, Integer.valueOf(time));

        if (falg) {
            return new R().setData(1);//1 - 设置提醒成功
        } else {
            stringRedisTemplate.opsForZSet().remove("tixing_zset", msg);
            return new R().setData(0);//0 - 取消提醒成功
        }
    }

    /**
     * 判断是否提醒
     * @param uid
     * @param gid
     * @return
     */
    @RequestMapping("/istixing")
    public R isTixing(Integer uid, Integer gid){
        String msg = uid + "_" + gid;
        Long result = stringRedisTemplate.opsForZSet().rank("tixing_zset", msg);
        return new R().setData(result != null ? result : -1);//1 - 已经设置 0 - 未设置
    }
}
